import 'package:dio/dio.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart' hide Response, FormData;
import 'package:yp/base/response_entity.dart';
import 'package:yp/base/response_list_entity.dart';
import 'package:yp/config/config.dart';
import 'package:yp/enum/view_state_error_type.dart';
import 'package:yp/exceptions/global_exception.dart';
import 'package:yp/router.dart';
import 'package:yp/util/util.dart';

import '../logic.dart';

/// 封装网络请求 比如get post delete等
/// T 表示返回的是否是集合，有HttpResponseEntity和HttpResponseListEntity两种
/// G 表示返回的是接口返回的类型（即你需要的类型）
typedef HttpCallBack<P> = dynamic Function(P response);

enum HttpMethod { GET, POST, DELETE, PUT, PATCH }

class ApiService {
  Dio dio;

  ApiService({this.dio});

  /// get 请求体
  Stream<dynamic> get<T, G>(
    String url, {
    dynamic data,
    HttpCallBack reLoginCallBack,
    HttpCallBack errorCallback,
  }) {
    return Stream.fromFuture(
      _sendRequest<T, G>(
        url,
        HttpMethod.GET,
        data: data,
        reLoginCallBack: reLoginCallBack,
        errorCallback: errorCallback,
      ),
    ).asBroadcastStream();
  }

  /// post 请求体
  Stream post<T, G>(
    String url, {
    dynamic data,
    Map<String, dynamic> queryParameters,
    HttpCallBack reLoginCallBack,
    HttpCallBack errorCallback,
  }) {
    return Stream.fromFuture(
      _sendRequest<T, G>(
        url,
        HttpMethod.POST,
        data: data,
        queryParameters: queryParameters,
        reLoginCallBack: reLoginCallBack,
        errorCallback: errorCallback,
      ),
    ).asBroadcastStream();
  }

  /// delete 请求体
  Stream delete<T, G>(
    String url, {
    dynamic data,
    Map<String, dynamic> queryParameters,
    HttpCallBack reLoginCallBack,
    HttpCallBack errorCallback,
  }) {
    return Stream.fromFuture(
      _sendRequest<T, G>(
        url,
        HttpMethod.DELETE,
        data: data,
        queryParameters: queryParameters,
        reLoginCallBack: reLoginCallBack,
        errorCallback: errorCallback,
      ),
    ).asBroadcastStream();
  }

  /// put 请求体
  Stream put<T, G>(
    String url, {
    dynamic data,
    Map<String, dynamic> queryParameters,
    HttpCallBack reLoginCallBack,
    HttpCallBack errorCallback,
  }) {
    return Stream.fromFuture(
      _sendRequest<T, G>(
        url,
        HttpMethod.PUT,
        data: data,
        queryParameters: queryParameters,
        reLoginCallBack: reLoginCallBack,
        errorCallback: errorCallback,
      ),
    ).asBroadcastStream();
  }

  /// 发送请求
  Future _sendRequest<T, G>(
    String url,
    HttpMethod method, {
    dynamic data,
    Map<String, dynamic> queryParameters,
    HttpCallBack reLoginCallBack,
    HttpCallBack errorCallback,
  }) async {
    try {
      Response response;

      /// GET

      // if (method == HttpMethod.GET) {
      //   if (data == null) {
      //     response = await dio.get(url);
      //   } else {
      //     response = await dio.get(
      //       url,
      //       queryParameters: data,
      //     );
      //   }
      // }

      if (method == HttpMethod.GET) {
        if (data == null) {
          response = await dio.get('');
        } else {
          response = await dio.get(
            '',
            queryParameters: buildParams(method: url, params: data),
          );
        }
      }

      ///  POST
      if (method == HttpMethod.POST) {
        print('上传图片');
        print(data.runtimeType.toString() == 'FormData');
        if (data is FormData) {
          response = await dio.post(
            url,
            data: data,
            queryParameters: queryParameters,
          );
        } else {
          if (data == null) {
            print('上传图片2');
            response = await dio.post(
              url,
              queryParameters: queryParameters,
            );
          } else {
            print('上传图片3');
            response = await dio.post(
              '',
              data: buildParams(method: url, params: data),
              queryParameters: queryParameters,
            );
          }
        }
      }

      ///  DELETE
      if (method == HttpMethod.DELETE) {
        if (data == null) {
          response = await dio.delete(url);
        } else {
          response = await dio.delete(
            url,
            data: data,
            queryParameters: queryParameters,
          );
        }
      }

      ///  PUT
      if (method == HttpMethod.PUT) {
        if (data == null) {
          response = await dio.put(url);
        } else {
          response = await dio.put(
            url,
            data: data,
            queryParameters: queryParameters,
          );
        }
      }

      /// 接口code对应的字段名
      var codeFieldName = Config.API_CODE_FIELD_NAME;

      /// 接口message对应的字段名
      var messageFieldName = Config.API_MESSAGE_FIELD_NAME;

      /// 接口成功时的状态码
      var successCode = Config.API_SUCCESS_CODE;

      if (response.statusCode == 200) {
        var resultCode = response.data[codeFieldName].toString();
        var msg = response.data[messageFieldName].toString();

        /// http状态吗为401时 跳到登陆页面
        if (resultCode.toString() == "-20050") {
          final GlobalLogic logic1 = Get.put(GlobalLogic());
          logic1.logout();

          EasyLoading.dismiss();
          Get.toNamed(RouteConfig.mallLogin);
        }

        if (resultCode.toString() == "-30034") {
          final GlobalLogic logic1 = Get.put(GlobalLogic());
          logic1.logout();
          EasyLoading.dismiss();
          Get.toNamed(RouteConfig.mallLogin);
        }
        if (resultCode.toString() == "-20999") {
          final GlobalLogic logic1 = Get.put(GlobalLogic());
          logic1.logout();
          EasyLoading.dismiss();
          //Get.offNamed(RouteConfig.mallLogin);

          Get.toNamed(RouteConfig.mallLogin);
        }

        if (resultCode.toString() == "-43044") {
          final GlobalLogic logic1 = Get.put(GlobalLogic());
          logic1.logout();
          EasyLoading.dismiss();
          //Get.offNamed(RouteConfig.mallLogin);
          Get.toNamed(RouteConfig.mallLogin);
        }

        if (resultCode.toString() == "-40002") {
          EasyLoading.dismiss();
          toast(response.data['message'].toString());
        }
        // if (resultCode.toString() != "0" &&
        //     resultCode.toString() != "-20051"" &&
        //     resultCode.toString() != "-20999") {
        //   toast(msg);
        // }

        /// 根据接口状态码验证成功

        // if (resultCode == successCode) {
        Map<String, dynamic> data = response.data;
        return _httpSuccess<T, G>(data);
        // } else {
        //   var msg = response.data[messageFieldName];
        //   throw _httpError(
        //     resultCode,
        //     msg,
        //     errorCallBack: errorCallback,
        //     reLoginCallBack: reLoginCallBack,
        //     response: response,
        //     type: ViewStateErrorType.DEFAULT,
        //   );
        // }
      }

      /// 接口请求失败 http状态码 != 200
      var type = ViewStateErrorType.DEFAULT;
      if (response.statusCode == 401 || response.statusCode == 402) {
        type = ViewStateErrorType.UNAUTHORIZED;
      }
      if (response.statusCode == 500) {
        type = ViewStateErrorType.SERVER_ERROR;
      }
      throw _httpError(
        response.statusCode.toString(),
        response.statusMessage,
        errorCallBack: errorCallback,
        reLoginCallBack: reLoginCallBack,
        response: response,
        type: type,
      );
    } catch (e) {
      print("dio catch error:$e");
      if (e is GlobalException) {
        if (e.message.contains("已经过期")) {
          toast("帐号已在其它设备上登录");
        } else if (e.message.contains("短信验证码Tok")) {
          toast("意验证码错误");
        } else {
          toast(e.message);
        }
      }
      throw e;
    }
  }

  ///  接口请求成功
  _httpSuccess<T, G>(Map<String, dynamic> response) {
    if (T.toString() == "HttpResponseEntity<dynamic>") {
      return HttpResponseEntity<G>.fromJson(response).data;
    } else if (T.toString() == "HttpResponseListEntity<dynamic>") {
      return HttpResponseListEntity<G>.fromJson(response).data;
    } else {
      return response;
    }
  }

  /// http code != 200
  _httpError(
    String errorCode,
    String errorMsg, {
    HttpCallBack errorCallBack,
    HttpCallBack reLoginCallBack,
    RequestOptions request,
    Response response,
    ViewStateErrorType type,
  }) {
    if (reLoginCallBack != null) {
      reLoginCallBack(response);
    }
    if (errorCallBack != null) {
      errorCallBack(ErrorResponse(errorCode, errorMsg));
    }
    return GlobalException(
      response: response,
      request: request,
      type: type,
      error: errorMsg,
    );
  }
}

class ErrorResponse {
  String resultCode;
  String message;

  ErrorResponse(this.resultCode, this.message);

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['resultCode'] = this.resultCode;
    data['message'] = this.message;
    return data;
  }
}
